<template>
    <div class="content">
      <div class="left card">
        <div class="card-head">
          <p>
            <span>cron配置</span>
          </p>
        </div>
        <div class="card-body">
          <Tabs size="small" v-model="curtab">
            <TabPane label="秒" name="second" v-if="!hideSecond">
              <second-ui v-model="second" :disabled="disabled"></second-ui>
            </TabPane>
            <TabPane label="分" name="minute">
              <minute-ui v-model="minute" :disabled="disabled"></minute-ui>
            </TabPane>
            <TabPane label="时" name="hour">
              <hour-ui v-model="hour" :disabled="disabled"></hour-ui>
            </TabPane>
            <TabPane label="日" name="day">
              <day-ui v-model="day" :week="week" :disabled="disabled"></day-ui>
            </TabPane>
            <TabPane label="月" name="month">
              <month-ui v-model="month" :disabled="disabled"></month-ui>
            </TabPane>
            <TabPane label="周" name="week">
              <week-ui v-model="week" :day="day" :disabled="disabled"></week-ui>
            </TabPane>
            <TabPane label="年" name="year" v-if="!hideYear && !hideSecond">
              <year-ui v-model="year" :disabled="disabled"></year-ui>
            </TabPane>
          </Tabs>
        </div>
      </div>
      <div class="right card">
        <div class="card-head">
          <p>
            <span>表达式</span>
          </p>
        </div>
        <div class="card-body">
        <div class="field-list">
          <Table stripe border disabled-hover :show-header="false" :columns="columns" :data="tableData" size="small"></Table>
        </div>
        <div class="exe-pre">
          <div class="exe-pre-panel">
            <label class="p-left">执行时间</label>
            <DatePicker type="datetime" v-model="startTime" class="p-right"
              placeholder="选择执行开始时间"></DatePicker>
          </div>
          <div class="exe-pre-panel">
            <Tooltip content="执行预览解析不含年参数" class="p-left">
              <label>执行预览</label>
            </Tooltip>
            <Input type="textarea" :value="preTimeList" class="p-right" :rows="4" readonly />
          </div>
        </div>
        </div>
        </div>
    </div>
</template>

<script>
import SecondUi from './tabs/second'
import MinuteUi from './tabs/minute'
import HourUi from './tabs/hour'
import DayUi from './tabs/day'
import WeekUi from './tabs/week'
import MonthUi from './tabs/month'
import YearUi from './tabs/year'
import CronParser from 'cron-parser'
import { debounce } from 'debounce'

export default {
  name: 'easy-cron',
  model: {
    prop: 'cronValue',
    event: 'change'
  },
  props: {
    cronValue: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    },
    exeStartTime: {
      type: [Number, String, Object],
      default: 0
    },
    hideSecond: {
      type: Boolean,
      default: false
    },
    hideYear: {
      type: Boolean,
      default: false
    },
    remote: {
      type: Function,
      default: null
    }
  },
  data () {
    return {
      curtab: this.hideSecond ? 'minute' : 'second',
      second: '*',
      minute: '*',
      hour: '*',
      day: '*',
      month: '*',
      week: '?',
      year: '*',
      startTime: new Date(),
      preTimeList: '执行预览，会忽略年份参数'
    }
  },
  computed: {
    columns () {
      return [{ title: ' ', key: 'name' }, { title: ' ', key: 'value' }]
    },
    tableData () {
      let c = this.hideSecond ? [] : [{ name: '秒', value: this.second }]
      c = c.concat([
        { name: '分', value: this.minute },
        { name: '时', value: this.hour },
        { name: '日', value: this.day },
        { name: '月', value: this.month },
        { name: '周', value: this.week }
      ])
      return (this.hideSecond || this.hideYear) ? c.concat({ name: '表达式', value: this.cronValue_c })
        : c.concat(
          { name: '年', value: this.year },
          { name: '表达式', value: this.cronValue_c },
          { name: '表达式(不含年)', value: this.cronValue_c2 }
        )
    },
    cronValue_c () {
      let result = []
      if (!this.hideSecond) result.push(this.second ? this.second : '*')
      result.push(this.minute ? this.minute : '*')
      result.push(this.hour ? this.hour : '*')
      result.push(this.day ? this.day : '*')
      result.push(this.month ? this.month : '*')
      result.push(this.week ? this.week : '?')
      if (!this.hideYear && !this.hideSecond) result.push(this.year ? this.year : '*')
      return result.join(' ')
    },
    cronValue_c2 () {
      const v = this.cronValue_c
      if (this.hideYear || this.hideSecond) return v
      const vs = v.split(' ')
      return vs.slice(0, vs.length - 1).join(' ')
    }
  },
  watch: {
    cronValue (newVal, oldVal) {
      if (newVal === this.cronValue_c) {
        // console.info('same cron value: ' + newVal)
        return
      }
      this.formatValue()
    },
    cronValue_c (newVal, oldVal) {
      this.calTriggerList()
      this.$emit('change', newVal)
    },
    exeStartTime (newVal, oldVal) {
      this.calStartTime()
    },
    startTime (newVal, oldVal) {
      this.calTriggerList()
    }
  },
  methods: {
    formatValue () {
      // console.info(this.cronValue)
      if (!this.cronValue) return
      const values = this.cronValue.split(' ').filter(item => !!item)
      if (!values || values.length <= 0) return
      let i = 0
      if (!this.hideSecond) this.second = values[i++]
      if (values.length > i) this.minute = values[i++]
      if (values.length > i) this.hour = values[i++]
      if (values.length > i) this.day = values[i++]
      if (values.length > i) this.month = values[i++]
      if (values.length > i) this.week = values[i++]
      if (values.length > i) this.year = values[i]
    },
    calTriggerList: debounce(function () {
      this.calTriggerListInner()
    }, 500),
    calTriggerListInner () {
      // 设置了回调函数
      if (this.remote) {
        this.remote(this.cronValue_c2, +this.startTime, v => { this.preTimeList = v })
        return
      }
      // 去掉年份参数
      const e = this.cronValue_c2
      // console.info('>>>>>>' + e)
      const format = 'yyyy-MM-dd HH:mm:ss'
      const options = {
        currentDate: this.startTime.Format(format)
      }
      // console.info(options)
      const iter = CronParser.parseExpression(e, options)
      const result = []
      for (let i = 0; i < 5; i++) {
        result.push(new Date(iter.next()).Format(format))
      }
      this.preTimeList = result.length > 0 ? result.join('\n') : '无执行时间'
    },
    calStartTime () {
      if (!this.exeStartTime) {
        this.startTime = new Date()
        return
      }
      try {
        this.startTime = new Date(this.exeStartTime)
      } catch (e) {
        this.startTime = new Date()
      }
    }
  },
  components: {
    SecondUi,
    MinuteUi,
    HourUi,
    DayUi,
    WeekUi,
    MonthUi,
    YearUi
  },
  created () {
    this.formatValue()
    this.calStartTime()
    this.$nextTick(() => {
      this.calTriggerListInner()
    })
  }
}
</script>

<style scoped>
.content {
  display: flex;
  width: 100%;
  /*padding: 16px;*/
  /*border: 1px solid #dcdee2;*/
  /*border-radius: 4px;*/
}
.card{
  border: 1px solid #dcdee2;
  border-radius: 4px;
  transition: all .2s ease-in-out;
}
.card-head{
  border-bottom: 1px solid #e8eaec;
  padding: 14px 16px;
}
.card-body{
  padding: 16px;
}
.card-head p{
  height: 20px;
  line-height: 20px;
  font-size: 14px;
  color: #17233d;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.left {
  width: 56%;
}

.right {
  margin-left: 2%;
  width: 44%;
}
.exe-pre {
  margin-top: 5px;
}

.exe-pre > div {
  margin-top: 5px;
}

.exe-pre-panel {
  display: flex;
  justify-content: flex-start;
}

.exe-pre-panel .p-left {
  flex-basis: 80px;
  flex-grow: 0;
}

.exe-pre-panel .p-right {
  flex-basis: 100px;
  flex-grow: 1;
}
</style>
